//
//  BigInt.h
//  BigNum
//
//  Created by Sam Jaffe on 9/18/12.
//  Copyright (c) 2012 Sam Jaffe. All rights reserved.
//

#pragma once

#include "BigNum.h"
#include "BigUInt.h"

class BigInt : public BigUInt {
protected:
    bool is_negative;
public:
    BigInt(const unsigned long long value);
    BigInt();
    BigInt(const BigUInt& copy);
    BigInt(const BigUInt& copy, bool sign);
    BigInt(BigUInt&& copy);
    BigInt(const BigInt& copy);
    BigInt(BigInt&& copy);
    
    void sum(const BigInt& a, const BigInt& b);
    void diff(const BigInt& a, const BigInt& b);
    void product(const BigInt& a, const BigInt& b);
    void quotient(const BigInt& a, const BigInt& b);
    void modulo(const BigInt& a, const BigInt& b);
    
    void bflip(const BigInt& a);
    void band(const BigInt& a, const BigInt& b);
    void bor(const BigInt& a, const BigInt& b);
    void bxor(const BigInt& a, const BigInt& b);
    void bin(const BigInt& a, const BigInt& b);
    void bout(const BigInt& a, const BigInt& b);
        
    virtual BigNumber operator- () const;
    
    virtual bool operator== (const BigNumber& b) const;
    virtual bool operator!= (const BigNumber& b) const;
    virtual bool operator>= (const BigNumber& b) const;
    virtual bool operator> (const BigNumber& b) const;
    virtual bool operator<= (const BigNumber& b) const;
    virtual bool operator< (const BigNumber& b) const;
    
    virtual bool operator== (const BigInt& b) const;
    virtual bool operator!= (const BigInt& b) const;
    virtual bool operator>= (const BigInt& b) const;
    virtual bool operator> (const BigInt& b) const;
    virtual bool operator<= (const BigInt& b) const;
    virtual bool operator< (const BigInt& b) const;
    
    operator std::string() const;
};

inline bool BigInt::operator== (const BigInt& b) const {
    return this->is_negative xor b.is_negative and BigNumber::operator==(b);
}

inline bool BigInt::operator== (const BigNumber& b) const {
    return not(this->is_negative) and BigNumber::operator==(b);
}

inline bool BigInt::operator!= (const BigInt& b) const {
    return (this->is_negative xor b.is_negative) or BigNumber::operator!=(b);
}

inline bool BigInt::operator!= (const BigNumber& b) const {
    return this->is_negative or BigNumber::operator!=(b);
}

inline bool BigInt::operator>= (const BigInt& b) const {
    if (!this->is_negative and b.is_negative)
        return true;
    else if (this->is_negative)
        return b.BigNumber::operator>=(*this);
    else
        return BigNumber::operator>=(b);
}

inline bool BigInt::operator>= (const BigNumber& b) const {
    return !this->is_negative and BigNumber::operator>=(b);
}

inline bool BigInt::operator> (const BigInt& b) const {
    if (!this->is_negative and b.is_negative)
        return true;
    else if (this->is_negative)
        return b.BigNumber::operator>(*this);
    else
        return BigNumber::operator>(b);
}

inline bool BigInt::operator> (const BigNumber& b) const {
    return !this->is_negative and BigNumber::operator>(b);
}

inline bool BigInt::operator<= (const BigInt& b) const {
    if (this->is_negative and !b.is_negative)
        return true;
    else if (this->is_negative)
        return b.BigNumber::operator<=(*this);
    else
        return BigNumber::operator<=(b);
}

inline bool BigInt::operator<= (const BigNumber& b) const {
    return !this->is_negative and BigNumber::operator<=(b);
}

inline bool BigInt::operator< (const BigInt& b) const {
    if (this->is_negative and !b.is_negative)
        return true;
    else if (this->is_negative)
        return b.BigNumber::operator<(*this);
    else
        return BigNumber::operator<(b);
}

inline bool BigInt::operator< (const BigNumber& b) const {
    return !this->is_negative and BigNumber::operator>=(b);
}
